package com.example.demo.service;

import com.example.demo.mapper.UserCheckInMapper;
import com.example.demo.mapper.UserCreditMapper;
import com.example.demo.model.UserCheckIn;
import com.example.demo.model.UserCredit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class CheckInService {
    private final UserCheckInMapper checkInMapper;
    private final UserCreditMapper userCreditMapper;

    @Autowired
    public CheckInService(UserCheckInMapper checkInMapper, UserCreditMapper userCreditMapper) {
        this.checkInMapper = checkInMapper;
        this.userCreditMapper = userCreditMapper;
    }

    @Transactional
    public Map<String, Object> checkIn(Long userId) {
        Map<String, Object> response = new HashMap<>();
        LocalDate today = LocalDate.now();

        // 检查今日是否已签到
        if (checkInMapper.existsByUserIdAndCheckInDate(userId, today)) {
            response.put("success", false);
            response.put("message", "今日已签到");
            return response;
        }

        // 获取上次签到记录
        UserCheckIn lastCheckIn = checkInMapper.findFirstByUserIdOrderByCheckInDateDesc(userId);
        int consecutiveDays = 1;
        int pointsEarned = 10; // 基础积分

        // 计算连续签到天数
        if (lastCheckIn != null && lastCheckIn.getCheckInDate().plusDays(1).isEqual(today)) {
            consecutiveDays = calculateConsecutiveDays(userId, lastCheckIn.getCheckInDate());
            pointsEarned = 10 + (consecutiveDays > 7 ? 5 : consecutiveDays); // 连续7天后额外加5
        }

        // 保存签到记录
        UserCheckIn checkIn = new UserCheckIn();
        checkIn.setUserId(userId);
        checkIn.setCheckInDate(today);
        checkIn.setPointsEarned(pointsEarned);
        checkInMapper.insertCheckIn(checkIn);

        // 更新用户积分
        UserCredit credit = userCreditMapper.findByUserId(userId);
        if (credit == null) {
            credit = new UserCredit();
            credit.setUserId(userId);
            credit.setBalance(0);
            userCreditMapper.insertUserCredit(credit);
        }
        int newBalance = credit.getBalance() + pointsEarned;
        userCreditMapper.updateBalance(userId, newBalance);

        // 返回响应
        response.put("success", true);
        response.put("message", "签到成功");
        response.put("pointsEarned", pointsEarned);
        response.put("totalPoints", newBalance);
        return response;
    }

    public Map<String, Object> getCheckInStatus(Long userId) {
        Map<String, Object> response = new HashMap<>();
        LocalDate today = LocalDate.now();

        // 检查今日是否签到
        boolean checkedInToday = checkInMapper.existsByUserIdAndCheckInDate(userId, today);

        // 获取连续签到天数和最后签到日期
        UserCheckIn lastCheckIn = checkInMapper.findFirstByUserIdOrderByCheckInDateDesc(userId);
        int consecutiveDays = 0;
        LocalDate lastCheckInDate = null;

        if (lastCheckIn != null) {
            lastCheckInDate = lastCheckIn.getCheckInDate();
            if (lastCheckInDate.plusDays(1).isAfter(today)) {
                consecutiveDays = calculateConsecutiveDays(userId, lastCheckInDate);
            }
        }

        response.put("checkedInToday", checkedInToday);
        response.put("consecutiveDays", consecutiveDays);
        response.put("lastCheckInDate", lastCheckInDate);
        return response;
    }

    private int calculateConsecutiveDays(Long userId, LocalDate lastCheckInDate) {
        List<LocalDate> checkInDates = checkInMapper.findCheckInDatesAfter(userId, lastCheckInDate.minusDays(30));
        int consecutiveDays = 1;
        LocalDate current = lastCheckInDate;

        for (LocalDate date : checkInDates) {
            if (current.minusDays(1).isEqual(date)) {
                consecutiveDays++;
                current = date;
            } else {
                break;
            }
        }
        return consecutiveDays;
    }
}